home *** CD-ROM | disk | FTP | other *** search
/ Aminet 51 / Aminet 51 (2002)(GTI - Schatztruhe)[!][Oct 2002].iso / Aminet / util / conv / sapmaker.lha / SAP Maker / sapmaker.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-13  |  11.2 KB  |  503 lines

  1. /* SAP MAKER - Public Domain */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6.  
  7. #define word(l, h) ( ((h) << 8) | (l) )
  8. #define lo(x) ((x) & 0xff)
  9. #define hi(x) ((x) >> 8)
  10.  
  11. char author[300];
  12. char name[300];
  13. char date[300];
  14. int songs;
  15. int defsong;
  16. enum {
  17.     cmc = 0, cmr, mpt, md1, md2, tmc, tm8, ams, unknown
  18. } type;
  19. unsigned int music;
  20. unsigned int init;
  21. unsigned int player;
  22. char iname[300];
  23. char oname[300];
  24. FILE* ofile;
  25. unsigned char msx[63000];
  26. unsigned char* buf;
  27. unsigned char* smp;
  28. unsigned char* plr;
  29.  
  30. /* Read file to buffer */
  31. void readfile(char* name, int offset) {
  32.     FILE* tfile;
  33.     if (!(tfile = fopen(name, "rb"))) {
  34.         printf("Can't open %s\n", name);
  35.         exit(2);
  36.     }
  37.     fseek(tfile, offset, SEEK_CUR);
  38.     buf += fread(buf, 1, msx + sizeof(msx) - buf, tfile);
  39.     fclose(tfile);
  40. }
  41.  
  42. /* Create .SAP and write author,name,date,type */
  43. void saphdr(char t) {
  44.     if (strlen(oname) > 30)
  45.         printf("WARNING: File name \"%s\" longer than 30 characters\n", oname);
  46.     if (!(ofile = fopen(oname, "wb"))) {
  47.         printf("Can't create %s\n", oname);
  48.         exit(2);
  49.     }
  50.     fprintf(ofile,
  51.         "SAP\r\n"
  52.         "AUTHOR %s\r\n"
  53.         "NAME %s\r\n"
  54.         "DATE %s\r\n"
  55.         "TYPE %c\r\n",
  56.         author, name, date, t);
  57.     if (songs != 1) {
  58.         fprintf(ofile, "SONGS %d\r\n", songs);
  59.         if (defsong)
  60.             fprintf(ofile, "DEFSONG %d\r\n", defsong);
  61.     }
  62. }
  63.  
  64. /* Procs for different music formats */
  65. void cmc_() {
  66.     music = word(msx[2], msx[3]);
  67.     player = (music >= 0x1000 ? 0x500 : 0xf500);
  68.     readfile(type == cmr    ? (player == 0x500 ? "cmr_0500.plr" : "cmr_f500.plr")
  69.                 : (player == 0x500 ? "cmc_0500.plr" : "cmc_f500.plr")
  70.         , 2);
  71.     saphdr('C');
  72.     fprintf(ofile,
  73.         "MUSIC %04X\r\n"
  74.         "PLAYER %04X\r\n",
  75.         music, player);
  76. }
  77.  
  78. void mpt_() {
  79.     player = (msx[3] >= '\x10' ? 0x500 : 0xf500);
  80. /*    dta a(begin,end)
  81. ; = 4 bytes
  82.     ldy #<msx
  83.     ldx #>msx
  84.     lda #0
  85.     jsr player
  86.     ldx #0    ;song pos
  87.     lda #2
  88. ; = 13 bytes
  89. player    jmp init
  90.     jmp play
  91. */
  92.     plr = buf;
  93.     buf += 17;
  94.     readfile(player == 0x500 ? "mpt_0500.plr" : "mpt_f500.plr", 6);
  95.     plr[0] = lo(player - 13);        plr[1] = hi(player - 13);
  96.     plr[2] = lo(player - 16 + buf - plr);    plr[3] = hi(player - 16 + buf - plr);
  97.     plr[4] = '\xa0';    plr[5] = msx[2];
  98.     plr[6] = '\xa2';    plr[7] = msx[3];
  99.     plr[8] = '\xa9';    plr[9] = '\x00';
  100.     plr[10] = '\x20';    plr[11] = lo(player);    plr[12] = hi(player);
  101.     plr[13] = '\xa2';    plr[14] = '\x00';
  102.     plr[15] = '\xa9';    plr[16] = '\x02';
  103.     saphdr('B');
  104.     fprintf(ofile,
  105.         "INIT %04X\r\n"
  106.         "PLAYER %04X\r\n",
  107.         player - 13, player + 3);
  108. }
  109.  
  110. void readSamples(char* ext) {
  111.     smp = buf;
  112.     buf += 4;
  113.     strcpy(strrchr(iname, '.') + 1, ext);
  114.     readfile(iname, 0);
  115.     smp[0] = '\xe0';
  116.     smp[1] = smp[4] - 1;
  117.     smp[2] = '\xff';
  118.     smp[3] = smp[4] + hi(buf - smp - 0x25);
  119.     if (!(msx[5] < smp[1] || msx[3] > smp[3])) {
  120.         int i = hi(buf - smp - 0x25);
  121.         int h = 0x0e + i < msx[3] ? 0x0e : 0xcf - i;
  122.         printf("WARNING: Conflict between music and samples %s. Placing samples at $%02X00.\n", iname, h);
  123.         h -= smp[4];
  124.         smp[1] += h;
  125.         smp[3] += h;
  126.         for (i = 0; i < 0x20; i++)
  127.             if (smp[4 + i])
  128.                 smp[4 + i] += h;
  129.     }
  130.  
  131.     player = (msx[3] >= '\x10' && smp[4] >= '\x10' ? 0x500 : 0xf500);
  132. }
  133.  
  134. void md1_() {
  135.     FILE *tfile;
  136.     unsigned char is15kHz;
  137.     /* Check if there are .D15 samples */
  138.     strcpy(strrchr(iname, '.') + 1, "d15");
  139.     tfile = fopen(iname, "rb");
  140.     if (tfile != NULL) {
  141.         fclose(tfile);
  142.         /* Read .D15 samples */
  143.         readSamples("d15");
  144.         is15kHz = 1;
  145.     }
  146.     else {
  147.         /* Read .D8 samples */
  148.         readSamples("d8");
  149.         is15kHz = 0;
  150.     }
  151. /*    dta a(begin,end)
  152. ; = 4 bytes
  153.     ldy #<msx
  154.     ldx #>msx
  155.     lda #0
  156.     jsr player
  157.     ldy #<smp
  158.     ldx #>smp
  159.     lda #3
  160.     jsr player
  161.     ldx #0    ;song pos
  162.     lda #2
  163.     jsr player
  164.     ldx #1    ;0=7.5kHz 1=15kHz
  165.     lda #5
  166. ; = 29 bytes
  167. player    jmp init
  168.     jmp play
  169. */
  170.     plr = buf;
  171.     buf += 33;
  172.     readfile(player == 0x500 ? "mpt_0500.plr" : "mpt_f500.plr", 6);
  173.     plr[0] = lo(player - 29);        plr[1] = hi(player - 29);
  174.     plr[2] = lo(player - 32 + buf - plr);    plr[3] = hi(player - 32 + buf - plr);
  175.     plr[4] = '\xa0';    plr[5] = msx[2];
  176.     plr[6] = '\xa2';    plr[7] = msx[3];
  177.     plr[8] = '\xa9';    plr[9] = '\x00';
  178.     plr[10] = '\x20';    plr[11] = lo(player);    plr[12] = hi(player);
  179.     plr[13] = '\xa0';    plr[14] = '\xe0';
  180.     plr[15] = '\xa2';    plr[16] = smp[4] - 1;
  181.     plr[17] = '\xa9';    plr[18] = '\x03';
  182.     plr[19] = '\x20';    plr[20] = lo(player);    plr[21] = hi(player);
  183.     plr[22] = '\xa2';    plr[23] = '\x00';
  184.     plr[24] = '\xa9';    plr[25] = '\x02';
  185.     plr[26] = '\x20';    plr[27] = lo(player);    plr[28] = hi(player);
  186.     plr[29] = '\xa2';    plr[30] = is15kHz;
  187.     plr[31] = '\xa9';    plr[32] = '\x05';
  188.     saphdr('D');
  189.     fprintf(ofile,
  190.         "INIT %04X\r\n"
  191.         "PLAYER %04X\r\n",
  192.         player - 29, player + 3);
  193. }
  194.  
  195. void md2_() {
  196.     /* Read .D8 samples */
  197.     readSamples("d8");
  198. /*    dta a(begin,end)
  199. ; = 4 bytes
  200.     ldy #<msx
  201.     ldx #>msx
  202.     lda #0
  203.     jsr player
  204.     ldy #<smp
  205.     ldx #>smp
  206.     lda #3
  207.     jsr player
  208.     ldx #0    ;song pos
  209.     lda #2
  210.     jsr player
  211.     lda #6
  212. ; = 27 bytes
  213. */
  214.     plr = buf;
  215.     buf += 31;
  216.     readfile(player == 0x500 ? "mpt_0500.plr" : "mpt_f500.plr", 6);
  217.     plr[0] = lo(player - 27);        plr[1] = hi(player - 27);
  218.     plr[2] = lo(player - 30 + buf - plr);    plr[3] = hi(player - 30 + buf - plr);
  219.     plr[4] = '\xa0';    plr[5] = msx[2];
  220.     plr[6] = '\xa2';    plr[7] = msx[3];
  221.     plr[8] = '\xa9';    plr[9] = '\x00';
  222.     plr[10] = '\x20';    plr[11] = lo(player);    plr[12] = hi(player);
  223.     plr[13] = '\xa0';    plr[14] = '\xe0';
  224.     plr[15] = '\xa2';    plr[16] = smp[4] - 1;
  225.     plr[17] = '\xa9';    plr[18] = '\x03';
  226.     plr[19] = '\x20';    plr[20] = lo(player);    plr[21] = hi(player);
  227.     plr[22] = '\xa2';    plr[23] = '\x00';
  228.     plr[24] = '\xa9';    plr[25] = '\x02';
  229.     plr[26] = '\x20';    plr[27] = lo(player);    plr[28] = hi(player);
  230.     plr[29] = '\xa9';    plr[30] = '\x06';
  231.     saphdr('D');
  232.     fprintf(ofile,
  233.         "INIT %04X\r\n"
  234.         "PLAYER %04X\r\n",
  235.         player - 27, player + 3);
  236. }
  237.  
  238. void tmc_() {
  239.     int len;
  240.  
  241.     player  = (msx[3] >= '\x10' ? 0x500 : 0xf500);
  242. /*    dta a(begin,end)
  243. ; = 4 bytes
  244.     ldy #<msx
  245.     ldx #>msx
  246.     lda #$70
  247.     jsr player
  248.     lda #$60
  249. ; = 11 bytes
  250. ; 1/frame
  251. ; = 0 bytes
  252. player    jmp init
  253.     jmp play
  254.     jmp sound
  255. ; 2/frame - FASTPLAY 156
  256.     asl 0
  257.     jmp player
  258. play    lda 0
  259.     inc 0
  260.     lsr @
  261.     bcc player+3
  262.     bcs player+6 !
  263. ; = 14 bytes
  264. player
  265. ; 3/frame - FASTPLAY 104
  266.     ldx #1
  267.     stx 0
  268.     bne player !
  269. play    dec 0
  270.     bne player+6
  271.     ldx #3
  272.     stx 0
  273.     bne player+3 !
  274. ; = 16 bytes
  275. player
  276. ; 4/frame - FASTPLAY 78
  277.     ldx #1
  278.     stx 0
  279.     bne player !
  280. play    dec 0
  281.     bne player+6
  282.     ldx #4
  283.     stx 0
  284.     bne player+3 !
  285. ; = 16 bytes
  286. player
  287. */
  288.     plr = buf;
  289.     len = " \x0b\x19\x1b\x1b"[msx[37]];
  290.     buf += 4 + len;
  291.     readfile(player == 0x500 ? "tmc_0500.plr" : "tmc_f500.plr", 6);
  292.     init = player - len;
  293.     plr[0] = lo(init);            plr[1]=hi(init);
  294.     plr[2] = lo(init - 5 + buf - plr);    plr[3]=hi(init - 5 + buf - plr);
  295.     plr[4] = '\xa0';    plr[5] = msx[2];
  296.     plr[6] = '\xa2';    plr[7] = msx[3];
  297.     plr[8] = '\xa9';    plr[9] = '\x70';
  298.     plr[10] = '\x20';    plr[11] = lo(player);    plr[12] = hi(player);
  299.     plr[13] = '\xa9';    plr[14] = '\x60';
  300.     switch (msx[37]) {
  301.     case '\4':
  302.     case '\3':
  303.         plr[15] = '\xa2';    plr[16] = '\x01';
  304.         plr[17] = '\x86';    plr[18] = '\x00';
  305.         plr[19] = '\xd0';    plr[20] = '\x0a';
  306.         player -= 10;
  307.         plr[21] = '\xc6';    plr[22] = '\x00';
  308.         plr[23] = '\xd0';    plr[24] = '\x0c';
  309.         plr[25] = '\xa2';    plr[26] = msx[37];
  310.         plr[27] = '\x86';    plr[28] = '\x00';
  311.         plr[29] = '\xd0';    plr[30] = '\x03';
  312.         break;
  313.     case '\2':
  314.         plr[15] = '\x06';    plr[16] = '\x00';
  315.         plr[17] = '\x4c';    plr[18] = lo(player);    plr[19] = hi(player);
  316.         player -= 9;
  317.         plr[20] = '\xa5';    plr[21] = '\x00';
  318.         plr[22] = '\xe6';    plr[23] = '\x00';
  319.         plr[24] = '\x4a';
  320.         plr[25] = '\x90';    plr[26] = '\x05';
  321.         plr[27] = '\xb0';    plr[28] = '\x06';
  322.         break;
  323.     case '\1':
  324.         player += 3;
  325.         break;
  326.     }
  327.     saphdr('B');
  328.     if (type == tm8)
  329.         fprintf(ofile, "STEREO\r\n");
  330.     if (msx[37] > 1)
  331.         fprintf(ofile, "FASTPLAY %d\r\n", ((unsigned char *) "  \x9c\x68\x4e")[msx[37]]);
  332.     fprintf(ofile,
  333.         "INIT %04X\r\n"
  334.         "PLAYER %04X\r\n",
  335.         init, player);
  336. }
  337.  
  338. int convasc(unsigned char **pp)
  339. {
  340.     int r = 0;
  341.     unsigned char *p = *pp;
  342.     while (*p == ' ')
  343.         p++;
  344.     while (*p != 0x9b) {
  345.         if (*p == '.') {
  346.             while (*++p != 0x9b);
  347.             break;
  348.         }
  349.         r *= 10;
  350.         r += *p - '0';
  351.         p++;
  352.     }
  353.     *pp = p + 1;
  354.     return r;
  355. }
  356.  
  357. void ams_() {
  358.     int i;
  359.     unsigned char *p = msx;
  360.     unsigned int v[4];
  361.     unsigned int len = 0;
  362.     unsigned int m;
  363.     int time;
  364.     for (i = 0; i < 4; i++) {
  365.         len += convasc(&p);
  366.         v[i] = convasc(&p);
  367.     }
  368.     time = convasc(&p);
  369.     convasc(&p);
  370.     time = (385091 / time - 639) / 5.0234375;
  371.     p += len;
  372.     len = 2 * v[3];
  373.     memmove(msx + sizeof(msx) - len, p, len);
  374.  
  375.     buf = msx;
  376.     readfile("ams_0500.plr", 0);
  377.     m = word(msx[28], msx[29]) + 1;
  378.     p = msx + 6;
  379.     *p++ = lo(time);    *p++ = hi(time);
  380.     *p++ = lo(m);    *p++ = hi(m);
  381.     *p++ = lo(m + v[0]);    *p++ = hi(m + v[0]);
  382.     *p++ = lo(m + v[1]);    *p++ = hi(m + v[1]);
  383.     *p++ = lo(m + v[2]);    *p++ = hi(m + v[2]);
  384.     *p++ = lo(m + v[3]);    *p++ = hi(m + v[3]);
  385.     *p++ = lo(m + v[3] + v[0]);    *p++ = hi(m + v[3] + v[0]);
  386.     *p++ = lo(m + v[3] + v[1]);    *p++ = hi(m + v[3] + v[1]);
  387.     *p++ = lo(m + v[3] + v[2]);    *p++ = hi(m + v[3] + v[2]);
  388.     *p++ = lo(m + v[3] + v[3]);    *p++ = hi(m + v[3] + v[3]);
  389.     msx[28] = lo(m + len - 1);    msx[29] = hi(m + len - 1);
  390.     memmove(buf, msx + sizeof(msx) - len, len);
  391.     buf += len;
  392.     saphdr('D');
  393.     fprintf(ofile,
  394.         "INIT 0500\r\n"
  395.         "PLAYER 0503\r\n");
  396. }
  397.  
  398. int main(int argc, char** argv) {
  399.     char* exts[] = {"cmc", "cmr", "mpt", "md1", "md2", "tmc", "tm8", "ams"};
  400.     void (*procs[])() = {cmc_, cmc_, mpt_, md1_, md2_, tmc_, tmc_, ams_};
  401.     FILE* ifile;
  402.     char line[1000];
  403.     int i;
  404.     char* p;
  405.     char* q;
  406.     char* t[6];
  407.     unsigned endad;
  408.  
  409.     if (argc != 2) {
  410.         printf("SAP Maker v4 by Piotr Fusik/Fox/Taquart (fox@scene.pl) [070202]\n");
  411.         printf("Amiga port by Wojciech Pasiecznik/Voy/SSG/Dial (voydial@wp.pl)\n\n");
  412.         puts("Give info file name");
  413.         return 3;
  414.     }
  415.     if (!(ifile = fopen(argv[1], "r"))) {
  416.         printf("Can't open %s\n", argv[1]);
  417.         return 3;
  418.     }
  419.     while (!feof(ifile)) {
  420.         /* Get input and output names, songs, defsong */
  421.         fgets(line, sizeof(line), ifile);
  422.         if (feof(ifile))
  423.             break;
  424.         if (*line == ';' || *line == '\n')
  425.             continue;
  426.         switch (sscanf(line, "%s %s %d %d", iname, oname, &songs, &defsong)) {
  427.         case 0:
  428.             printf("Invalid line %s\n", line);
  429.             fclose(ifile);
  430.             return 2;
  431.         case 1:
  432.             sprintf(oname, "%.*s.sap", strrchr(iname, '.') - iname, iname);
  433.         case 2:
  434.             songs = 1;
  435.         case 3:
  436.             defsong = 0;
  437.         default:
  438.             break;
  439.         }
  440.         /* Recognize extension */
  441.         p = strrchr(iname, '.') + 1;
  442.         for (type = cmc; type < unknown; type++)
  443.             if (stricmp(p, exts[type]) == 0)
  444.                 break;
  445.         if (type == unknown) {
  446.             printf("Unknown type of %s\n", iname);
  447.             return 2;
  448.         }
  449.         /* Read music */
  450.         buf = msx;
  451.         readfile(iname, 0);
  452.         if (type != ams) {
  453.             if (msx[0] != 0xff || msx[1] != 0xff) {
  454.                 printf("%s is not valid music file\n", iname);
  455.                 return 2;
  456.             }
  457.             endad = word(msx[2], msx[3]) + buf - msx - 7;
  458.             if (endad != word(msx[4], msx[5]) ) {
  459.                 printf("WARNING: Fixing invalid header of %s\n", iname);
  460.                 msx[4] = lo(endad);
  461.                 msx[5] = hi(endad);
  462.             }
  463.         }
  464.         /* Get author, name and date */
  465.         /* Defaults: "<?>", "sap name", "<?>" */
  466.         strcpy(author, "\"<?>\"");
  467.         for(p = oname, q = name + 1; *p != '.'; p++, q++)
  468.             *q = (*p == '_' ? ' ' : *p);
  469.         *name = *q++ = '"';
  470.         *q = '\0';
  471.         strcpy(date, "\"<?>\"");
  472.         /* Find '"' */
  473.         p = line;
  474.         for (i = 0; i < 6; i++)
  475.             if(!(t[i] = p = strchr(p + 1, '"')))
  476.                 break;
  477.         /* Set author, name and date if given */
  478.         switch (i) {
  479.         case 6:
  480.             t[5][1] = '\0';
  481.             strcpy(date, t[4]);
  482.         case 5:
  483.         case 4:
  484.             t[3][1] = '\0';
  485.             strcpy(name, t[2]);
  486.         case 3:
  487.         case 2:
  488.             t[1][1] = '\0';
  489.             strcpy(author, t[0]);
  490.         default:
  491.             break;
  492.         }
  493.         /* Run proper procedure */
  494.         procs[type]();
  495.         /* Write binary part */
  496.         fwrite(msx, buf - msx, 1, ofile);
  497.         /* Close file */
  498.         fclose(ofile);
  499.     }
  500.     fclose(ifile);
  501.     return 0;
  502. }
  503.